/*
 +-----------------------------------------------------------------------------------------------+
 | Project : UKAPI
 +-----------------------------------------------------------------------------------------------+
 | Project Description : Universal & Kernel API
 +-----------------------------------------------------------------------------------------------+
 | File Description :
 |   Math
 |                                                 
 +-----------------------------------------------------------------------------------------------+
 | Licence : MIT Licence
 +-----------------------------------------------------------------------------------------------+
 | Copyright (c) 2006 Olivier Vanhoucke
 | 
 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
 | and associated documentation files (the "Software"), to deal in the Software without 
 | restriction, including without limitation the rights to use, copy, modify, merge, publish, 
 | distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 
 | Software is furnished to do so, subject to the following conditions:
 | 
 | The above copyright notice and this permission notice shall be included in all copies or 
 | substantial portions of the Software.
 | 
 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
 | BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 +-----------------------------------------------------------------------------------------------+
*/

/**
 * Inclusions standards
 */
#include <ukapi.h>

/**
 * Inclusions locales
 */
#include <math.h>

/*
 *	algorithm by
 *	D. P. Mitchell & J. A. Reeds
 */

#define	MATH_RAND_LEN		607
#define	MATH_RAND_TAP		273
#define	MATH_RAND_MASK		0x7fffffffL
#define	MATH_RAND_A			48271
#define	MATH_RAND_M			2147483647
#define	MATH_RAND_Q			44488
#define	MATH_RAND_R			3399

_private ulong_t	g_math_rng_vec[MATH_RAND_LEN];
_private pulong_t	g_math_rng_tap	= g_math_rng_vec;
_private pulong_t	g_math_rng_feed = null;

_private void math_internal_rand_set_seed( int32_t seed )
{
	int32_t lo, hi, x;
	int32_t i;

	g_math_rng_tap	= g_math_rng_vec;
	g_math_rng_feed	= g_math_rng_vec + MATH_RAND_LEN - MATH_RAND_TAP;
	seed			= seed % MATH_RAND_M;

	if ( seed < 0 )
	{
		seed += MATH_RAND_M;
	}

	if ( seed == 0 )
	{
		seed = 89482311;
	}

	x = seed;

	/*
	 *	Initialize by x[n+1] = 48271 * x[n] mod (2**31 - 1)
	 */
	for ( i = -20; i < MATH_RAND_LEN; i++ ) 
	{
		hi = x / MATH_RAND_Q;
		lo = x % MATH_RAND_Q;
		x = MATH_RAND_A * lo - MATH_RAND_R * hi;

		if ( x < 0 )
		{
			x += MATH_RAND_M;
		}

		if ( i >= 0 )
		{
			g_math_rng_vec[i] = x;
		}
	}
}

_public void math_rand_set_seed( int32_t seed )
{
	//lock(&lk);
	math_internal_rand_set_seed( seed );
	//unlock(&lk);
}

/*
// Maximum value that can be returned by the rand function.
#define RAND_MAX 0x7fff

static unsigned long long next = 1;

int rand( void )
{
  // This multiplier was obtained from Knuth, D.E., "The Art of
  //   Computer Programming," Vol 2, Seminumerical Algorithms, Third
  //   Edition, Addison-Wesley, 1998, p. 106 (line 26) & p. 108 
  next *= 6364136223846793005LL + 1;
  // was: next = next * 0x5deece66dLL + 11;
  return (int) ( ( next >> 21 ) & RAND_MAX );
}

void srand( unsigned seed )
{
	next = seed;
}
*/